package com.ds.infrastructure.hyperspace.container.flow.handler.grpc;

import com.ds.infrastructure.hyperspace.common.Container;
import com.ds.infrastructure.hyperspace.common.flow.FlowHandlerPipeline;
import com.ds.infrastructure.hyperspace.common.flow.handler.PostFlowHandler;
import com.ds.infrastructure.hyperspace.container.flow.context.HyperspaceDuplexFlowContext;
import com.ds.infrastructure.hyperspace.container.internal.http.NettyHttpHeaderNames;
import com.ds.infrastructure.hyperspace.container.internal.http2.HyperspaceHttp2FrameTypeEnum;
import com.ds.infrastructure.hyperspace.container.internal.http2.HyperspaceHttp2FrameWrapper;
import io.netty.handler.codec.HeadersUtils;
import io.netty.handler.codec.http2.Http2Headers;
import io.netty.handler.codec.http2.Http2HeadersFrame;
import io.netty.handler.codec.http2.Http2ResetFrame;
import org.apache.commons.lang3.StringUtils;

import static com.ds.infrastructure.hyperspace.container.internal.http2.HyperspaceHttp2FrameTypeEnum.HEADERS;
import static com.ds.infrastructure.hyperspace.container.internal.http2.HyperspaceHttp2FrameTypeEnum.RST_STREAM;

/**
 * grpc response code converter
 *
 * @Author: yaozh
 * @Description:
 */
public class GrpcResponseCodePostFlowHandler implements PostFlowHandler<HyperspaceDuplexFlowContext> {
    @Override
    public void handleOutput(HyperspaceDuplexFlowContext duplexFlowContext, Object data) {
        if (data instanceof HyperspaceHttp2FrameWrapper) {
            HyperspaceHttp2FrameWrapper http2FrameWrapper = (HyperspaceHttp2FrameWrapper) data;
            HyperspaceHttp2FrameTypeEnum frameType = http2FrameWrapper.getFrameType();
            if (HEADERS == frameType) {
                converter(duplexFlowContext, (Http2HeadersFrame) http2FrameWrapper.getFrameData());
                return;
            }
            if(RST_STREAM==frameType){
                converter(duplexFlowContext, (Http2ResetFrame) http2FrameWrapper.getFrameData());
            }
        }
    }

    private void converter(HyperspaceDuplexFlowContext duplexFlowContext, Http2HeadersFrame http2HeadersFrame) {
        Http2Headers http2Headers = http2HeadersFrame.headers();
        String status = HeadersUtils.getAsString(http2Headers, NettyHttpHeaderNames.STATUS);
        if (StringUtils.isEmpty(status)) {
            return;
        }
        String grpcStatus = HeadersUtils.getAsString(http2Headers, NettyHttpHeaderNames.GRPC_STATUS);
        if (StringUtils.isNotEmpty(grpcStatus)) {
            duplexFlowContext.setTargetResponseState(null, Integer.parseInt(grpcStatus));
            String grpcMessage=HeadersUtils.getAsString(http2Headers, NettyHttpHeaderNames.GRPC_MESSAGE);
            duplexFlowContext.setInterruptMessage(StringUtils.remove(grpcMessage,"\""));
            return;
        }
        duplexFlowContext.setTargetResponseState(null, Integer.parseInt(status));
    }
    private void converter(HyperspaceDuplexFlowContext duplexFlowContext, Http2ResetFrame http2ResetFrame) {
        Long errorCode = new Long(http2ResetFrame.errorCode());
        duplexFlowContext.setTargetResponseState(null,errorCode.intValue());
    }

    @Override
    public String handlerName() {
        return "grpcResponseCodePostHandler";
    }

    @Override
    public void initHandlerParameters(Container container, FlowHandlerPipeline pipeline, String[] handlerParams) {

    }
}
